Docker-Compose: Ejecutando una aplicación multicontenedor


Desde hace un par de días he estado probando Docker y, sobretodo, Docker Compose para ejecutar aplicaciones multicontenedor.

Me ha sido especialmente útil el artículo Dockerise your PHP application with Nginx and PHP7-FPMen el que se explica paso a paso cómo contruir el fichero docker-compose.yml desde cero, de forma progresiva. El artículo tiene una segunda parte, actualizada, corrigiendo algunos fallos del primer artículo y actualizando el fichero a la nueva versión de YAML.

El ejercicio que me he propuesto consistía en intentar dockerizar el wiki que tengo montado en casa sobre una Raspberry Pi. Para ello, necesitaba tres contenedores: uno con el servidor web, otro con PHP y otro con los datos (con Dokuwiki). Siguiendo el tutorial de The Geeky Platypus he puesto en marcha el servidor web con PHP y he publicado un fichero index.php con el clásico phpinfo();.

Animado por el éxito de crear la primera aplicación multicontenedor, decidí dar un paso más e intentar publicar más que un solo fichero. Así que me lancé a probar publicando la carpeta Dokuwiki. Por algún motivo, no funcionó.

Después de mucho investigar, al parecer el problema está en los permisos.

El problema está en que el usuario por defecto en un contenedor es root. Esto supone un problema de seguridad, por lo que las buenas prácticas recomiendan cambiar a otro usuario no privilegiado tan pronto como se pueda dentro del contenedor. Sin embargo, el montaje del volumen de datos se realiza como root (bug del 2013 Add ability to mount volume as user other than root #2259, que sigue abierto).

No tengo muy claro cómo funcionan los permisos en Docker, pero parece que se dan un conjunto de problemas debidos a las diferencias entre los usuarios en el contenedor y los usuarios locales (en realidad, sus UID y GID). Si en el contenedor se usa el usuario root, los ficheros que se crean en el volumen local no pueden borrarse (o editarse) con usuarios no privilegiados (fuera del contenedor). Si se usa un usuario diferente a root, al no existir en el sistema local, no puede accederse a los ficheros y otras situaciones parecidas en ese sentido.

En los tutoriales de internet que he seguido en internet todo funciona sin problemas, lo que me saca de quicio; pese a que aparentemente sigo los pasos del mismo modo, no funciona cuando lo intento yo.

En el caso concreto de un tutorial que encontré ayer, he conseguido indentificar varias diferencias. Por un lado, la imagen base que se usa en el tutorial es una imagen creada por un usuario, no la imagen oficial de Nginx. En la imagen oficial se crea el usuario y grupo nginx y en el fichero de configuración se cambia a este usuario (no privilegiado). En la imagen del usuario del tutorial, se realiza una instalación desde el repositorio de la imagen base (del sistema operativo) y únicamente se añade el parámetro daemon off en el fichero de configuración. Eso significa que Nginx se ejecuta como root en el contenedor construido a partir de esa imagen, lo que evitaría los problemas de permisos con los que me he topado una y otra vez.

Otra diferencia -y en este caso, de bulto- es que la carpeta local donde se encuentra Dokuwiki no está mapeada como volumen en el servidor web, con lo que la credibilidad del tutorial es bastante cuestionable (por eso no lo enlazo).

Una vez identificadas las diferencias con el tutorial que intentaba seguir, conseguía arrancar el servidor web sin problemas, aunque no podía interpretar ficheros en PHP. La página servida por Nginx era la página de bienvenida por defecto, lo que apuntaba a un problema con el "montado" del volumen local en el contenedor o un problema de permisos.

He entrado como root (mediante docker exec) en los contenedores y he comprobado que los volúmenes estaban montados correctamente, en las rutas correctas, lo que dejaba únicamente como opción los permisos. Para verificar esta hipótesis, he modificado los permisos de la carpeta Dokuwiki (mediante chmod 777 -R), dando permisos a todos los usuarios y ¡ha funcionado!

Obviamente, dar permisos a todos los usuarios sobre el volumen de datos no es la mejor idea del mundo, pero por el momento funciona. El siguiente paso es probar a mover el volumen de datos a un contenedor, con lo que intentaré minimizar o eliminar la necesidad de dar permisos a todo el mundo sobre el volumen de datos.

Como siempre, seguiré informando.

P.S: He escrito el artículo basándome en las notas para mí mismo que tomé durante las pruebas para crear la aplicación Dokuwiki multicontenedor. He repetido las pruebas para comprobar que el problema está en los permisos de la carpeta del host que se monta en los contenedores. Mi intención es escribir un segundo artículo más técnico, explicando paso a paso cómo crear el fichero docker-compose.yml. Si las pruebas que estoy haciendo dan resultado, espero poder eliminar el volumen de datos y usar un contenedor de datos.

Comentarios